package com.qs.dao;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Example;

import com.qs.entities.User;

public class UserDAO extends BaseHibernateDAO {
	
	private static final Logger log = Logger.getLogger(UserDAO.class);
	
	// property constants
	public static final String FIRST_NAME = "firstName";
	public static final String LAST_NAME = "lastName";
	public static final String SCREEN_NAME = "screenName";
	public static final String EMAIL = "email";
	public static final String PASSWORD = "password";
	public static final String ADDRESS = "address";
	public static final String PHONE = "phone";
	public static final String IS_LOGIN = "isLogin";
	public static final String MULTI_LOGIN_ALLOWED = "multiLoginAllowed";

	public void save(User transientInstance) {
		log.debug("saving User instance");
		Session session = null;
    	Transaction tx = null;
		try {
			session = getSession();
			tx 		= session.beginTransaction();
			session.save(transientInstance);
			tx.commit();
			log.debug("save successful");
		} catch (RuntimeException re) {
			log.error("save failed", re);
			try{
				tx.rollback();
			}
			catch(RuntimeException rbe){
				log.error("Couldn't roll back transaction", rbe);
			}
			throw re;
		}
		finally{
			if(session!=null)
				session.close();
		}
	}

	public void delete(User persistentInstance) {
		log.debug("deleting User instance");
		try {
			getSession().delete(persistentInstance);
			log.debug("delete successful");
		} catch (RuntimeException re) {
			log.error("delete failed", re);
			throw re;
		}
	}

	public User findById(java.lang.String id) {
		log.debug("getting User instance with id: " + id);
		try {
			User instance = (User) getSession().get("User", id);
			return instance;
		} catch (RuntimeException re) {
			log.error("get failed", re);
			throw re;
		}
	}

	public List findByExample(User instance) {
		log.debug("finding User instance by example");
		try {
			List results = getSession().createCriteria("User")
					.add(Example.create(instance)).list();
			log.debug("find by example successful, result size: "
					+ results.size());
			return results;
		} catch (RuntimeException re) {
			log.error("find by example failed", re);
			throw re;
		}
	}

	public List<User> findByProperty(String propertyName, Object value) {
		log.debug("finding User instance with property: " + propertyName
				+ ", value: " + value);
		try {
			String queryString = "from User as model where model."
					+ propertyName + "= ?";
			Query queryObject = getSession().createQuery(queryString);
			queryObject.setParameter(0, value);
			return queryObject.list();
		} catch (RuntimeException re) {
			log.error("find by property name failed", re);
			throw re;
		}
	}
	
	public List<User> findByProperty(String propertyName1, Object value1,String propertyName2, Object value2) {
		log.debug("finding User instance with property: " + propertyName1
				+ ", value: " + value1);
		try {
			String queryString = "from User as model where model."+ propertyName1 + "= ? AND model."+propertyName2+"= ?";
			Query queryObject = getSession().createQuery(queryString);
			queryObject.setParameter(0, value1);
			queryObject.setParameter(1, value2);
			return queryObject.list();
		} catch (RuntimeException re) {
			log.error("find by property name failed", re);
			throw re;
		}
	}

	public List<User> findByFirstName(Object firstName) {
		return findByProperty(FIRST_NAME, firstName);
	}

	public List findByLastName(Object lastName) {
		return findByProperty(LAST_NAME, lastName);
	}

	public List findByScreenName(Object screenName) {
		return findByProperty(SCREEN_NAME, screenName);
	}

	public List<User> findByEmail(Object email) {
		return findByProperty(EMAIL, email);
	}
	
	public List<User> findByEmailAndPassword(Object email,Object password) {
		return findByProperty(EMAIL, email, PASSWORD,password);
	}

	public List findByPassword(Object password) {
		return findByProperty(PASSWORD, password);
	}

	public List findByAddress(Object address) {
		return findByProperty(ADDRESS, address);
	}

	public List findByPhone(Object phone) {
		return findByProperty(PHONE, phone);
	}

	public List findByIsLogin(Object isLogin) {
		return findByProperty(IS_LOGIN, isLogin);
	}

	public List findByMultiLoginAllowed(Object multiLoginAllowed) {
		return findByProperty(MULTI_LOGIN_ALLOWED, multiLoginAllowed);
	}

	public List findAll() {
		log.debug("finding all User instances");
		try {
			String queryString = "from User";
			Query queryObject = getSession().createQuery(queryString);
			return queryObject.list();
		} catch (RuntimeException re) {
			log.error("find all failed", re);
			throw re;
		}
	}

	public User merge(User detachedInstance) {
		log.debug("merging User instance");
		try {
			User result = (User) getSession().merge(detachedInstance);
			log.debug("merge successful");
			return result;
		} catch (RuntimeException re) {
			log.error("merge failed", re);
			throw re;
		}
	}

	public void attachDirty(User instance) {
		log.debug("attaching dirty User instance");
		try {
			getSession().saveOrUpdate(instance);
			log.debug("attach successful");
		} catch (RuntimeException re) {
			log.error("attach failed", re);
			throw re;
		}
	}

	public void attachClean(User instance) {
		log.debug("attaching clean User instance");
		try {
			getSession().buildLockRequest(LockOptions.NONE).lock(instance);
			log.debug("attach successful");
		} catch (RuntimeException re) {
			log.error("attach failed", re);
			throw re;
		}
	}
}